Add doc search command (JSON documentation search)#7770
Conversation
| */ | ||
| export interface search { | ||
| /** | ||
| * Limit results to a specific API (for example: admin, storefront, hydrogen, functions). Unrecognized values are ignored. |
| Starts a search on shopify.dev. | ||
| Query the shopify.dev vector store and print the most relevant documentation chunks as JSON. Best for programmatic | ||
| discovery — surfacing the relevant pieces of documentation for a topic, rather than retrieving a whole document. To | ||
| download a full document verbatim, use `fetch-doc`. |
There was a problem hiding this comment.
Should discuss this contract with @nickwesselman . I'd assume that shopify search could just have a --fetch-doc param rather than a whole separate command for that case.
|
Having second thoughts about using I'm sure use of This would also give us an opportunity to apply our CLI design guidelines to a new command. e.g. The |
2f4b95a to
b8d45bd
Compare
shopify search to query the dev-assistant vector store as JSONdoc search command (JSON documentation search)
f0656f4 to
848fa45
Compare
| static description = | ||
| 'Query the shopify.dev vector store and print the most relevant documentation chunks as JSON. Best for programmatic discovery — surfacing the relevant pieces of documentation for a topic, rather than retrieving a whole document. To download a full document verbatim, use `doc fetch`.' | ||
|
|
||
| static usage = `doc search [query]` |
There was a problem hiding this comment.
nit: doc search since query is required
| if (apiName) params.append('api_name', apiName) | ||
| if (apiVersion) params.append('api_version', apiVersion) | ||
|
|
||
| const response = await fetch(`${SEARCH_URL}?${params.toString()}`, { |
There was a problem hiding this comment.
also need to handle network errors gracefully
|
Looking through the existing cli monorail schema, nothing stands out to me as a pre-existing fit for capturing doc search results. My suggestion would be that we add a new monorail field Additionally, currently the So, if this sounds reasonable, I can update the monorail schema to include |
|
@kaylarobinson077 - I think the cleaner solution for tracking search would be on the search handler. That one hanbdler is where all search traffic goes already |
…JSON The `search` command opened a browser at shopify.dev?search=<query>, which now redirects to the docs SPA and silently drops the query — so it has been broken for users while still being invoked ~70-100x/month. Repurpose it as an agent-facing JSON tool: it queries the dev-assistant vector store (GET https://shopify.dev/assistant/search) and prints the matching documentation chunks as JSON to stdout. No browser. This complements `fetch-doc` (verbatim full-document retrieval) as the "chunked discovery" half. - `query` is now required. - Adds `--api-name` and `--api-version` filters, passed through to the server. - 400 responses surface the server's error message (e.g. valid api_version list). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per the doc-namespace plan, the JSON vector-store search lives at `doc search` instead of repurposing the top-level `search` command: - Add commands/doc/search.ts (class DocSearch), services/commands/doc/search.ts (docSearchService), and the colocated test; register as `doc:search`. - Add a `doc` topic description. - Revert the breaking change to top-level `search` — it goes back to the original browser behavior (handled/deprecated separately in #7778). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Identifies the CLI as the calling surface to shopify.dev so traffic originating from the CLI can be attributed as such. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- usage now reads `doc search <query>` since the arg is required - use shopifyFetch (proper TLS + automatic retries for a Shopify service) - handle network failures gracefully with a friendly AbortError - regenerate oclif manifest + README for the usage change Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per the CLI design guidelines: flags make intent explicit, don't rely on order, and are easier to evolve. Regenerated manifest + README. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ba8ac8e to
550fbb3
Compare
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationsWe found no new type declarations in this PR Existing type declarationspackages/cli-kit/dist/public/node/session.d.ts@@ -47,6 +47,22 @@ export declare function isUserAccount(account: AccountInfo): account is UserAcco
* @returns True if the account is a ServiceAccount.
*/
export declare function isServiceAccount(account: AccountInfo): account is ServiceAccountInfo;
+/**
+ * Reports whether the CLI already has stored credentials, without prompting the
+ * user, opening a browser, or making any network request.
+ *
+ * This is a passive, side-effect-free check: it reads the local session store and
+ * returns when at least one valid session is present. Unlike the
+ * functions, it never triggers a login flow and never logs
+ * the user out. Because it does not contact the network, it cannot tell whether the
+ * stored token is currently valid/unexpired — only that credentials exist locally.
+ *
+ * Intended for best-effort, opportunistic behaviour (for example, enriching
+ * telemetry only for users who are already logged in).
+ *
+ * @returns True if local credentials exist, false otherwise.
+ */
+export declare function sessionExists(): Promise<boolean>;
/**
* Ensure that we have a valid session with no particular scopes.
*
|
Is the search handler something that lives within this command, or is it something outside of CLI? My home is that we can track the query and result in the regular CLI monorail event, so everything lives together in one place in terms of where the data lands. |
Assisted-By: devx/214c76e8-6ac0-48f1-bff5-0ef68c95d938
Assisted-By: devx/214c76e8-6ac0-48f1-bff5-0ef68c95d938
What
Adds
shopify doc search --query <query>, which queries the shopify.dev vector store and prints the most relevant documentation chunks as JSON to stdout.This is the "discovery" half of the new
docnamespace; the "full document" half isdoc fetch(#7766). It no longer repurposes the top-levelsearchcommand — that stays as the human, browser-based command (and is deprecated separately in #7778).Why
Gives agents (and scripts) a way to discover relevant documentation across shopify.dev as structured JSON, without a browser. Paired with
doc fetch, an agent can find the right docs and pull them in full, entirely through the CLI.Details
shopify doc search --query "<query>"— required query; prints the raw JSON response.--api-name(e.g.admin,storefront,hydrogen,functions; unknown values ignored).--api-version(e.g.2025-10,latest,current).{error}message (e.g. an invalid version lists the valid ones).🎩 Testing instructions
doc searchhits a public endpoint on shopify.dev (/assistant/search) — no auth, no app, no login required. It just needs network access and prints JSON to stdout.Run commands from the repo root via
node packages/cli/bin/dev.js …:1. Basic query → well-formed JSON
2. API/version filters are forwarded
3. Invalid version (with an api-name) surfaces the helpful error
Note: the endpoint only validates the version in the context of an
--api-name. A bad--api-versionon its own is silently ignored and still returns results.4. Required arg + help
Inspecting the Monorail analytics payload
This branch is rebased on the app-context telemetry PR (#7771), so every command emits a command-analytics event. To see exactly what would be sent to Monorail — without sending it — set two env vars:
SHOPIFY_CLI_NO_ANALYTICS=1— dump the payload via debug logging instead of POSTing it.SHOPIFY_FLAG_VERBOSE=1— raise the log level so the debug line prints.To confirm the inherited app-context hook, run the same command from inside an app directory while logged in — the payload then also carries app-level identifiers (
api_key,project_type,app_*). Run it from a non-app directory and those fields are absent.I saw the APP metrics broadcast via monorail when executing in the path of an app.
When not in the path of an app (in this case in the path of the CLI that I pulled down) - I did not broadcast app context.

Related
shopify doc fetchcommand to download MD doc from shopify.dev #7766 —doc fetch(full-document retrieval).search#7778 — deprecates the old browsersearch, pointing users todoc search.🤖 Generated with Claude Code